"""
@author: Zhang Wenzhou
@file: auth.py
@time: 2023/3/6 0006 14:34:44
"""
"""
权限认证
"""

# 授权装饰器
import time
from flask import request, current_app
from libs.response import response_data
from model.userdb.userinfo import ApiToken
from hashlib import md5
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from itsdangerous import BadSignature, SignatureExpired
from libs.error_code import TokenFailException

def login(func):
    def inner(*args, **kwargs):
        api_flag = request.args.get("api")
        if str(api_flag) == "1":    # 如果出入的api值是1，就进行api授权认证
            result = api_auth()
        else:   # 其他情况进行用户登录授权认证
            result = user_auth()
        if result:
            result = func(*args, **kwargs)
            return result
        else:
            return response_data(code=3, message="认证失败"), 401
    return inner

def api_auth():
    params = request.args  # 客户端url传递过来的参数
    appid = params.get("appid")
    salt = params.get("salt")  # 盐值
    sign = params.get("sign")  # 签名
    timestamp = params.get("timestamp")  # 时间戳

    if time.time() - float(timestamp) > 600:
        return False

    api_token = ApiToken.query.filter_by(appid=appid).first()
    if not api_token:
        return False

    # 验证有没有此url和方法的权限
    # http://127.0.0.1:8000/v1/monitor   GET
    #                                /v1/monitor         get
    if not has_permission(api_token, request.path, request.method.lower()):
        return False
    # 获取数据库里的密钥

    secretkey = api_token.secretkey
    # 生成服务端的签名
    # 可以加上时间戳来防止签名被别人盗取，重复访问
    user_sign = appid + salt + secretkey + timestamp
    # user_sign = appid + salt + secretkey
    m1 = md5()
    m1.update(user_sign.encode(encoding="utf-8"))
    # 判断客户端传递过来的签名和服务端生成签名是否一致
    if sign != m1.hexdigest():
        # raise AuthFailException
        return False
    else:
        return True


# url验证
# http://127.0.0.1:8000/v1/monitor   GET
#                apptest对象  /v1/monitor   get
def has_permission(api_token, url, method):
    # 客户端请求的方法和url
    # get/v1/monitor
    mypermission = method + url
    # 获取此api_token对象的所有url权限
    all_permission = [permission.method_type + permission.url
                      for permission in api_token.manage]
    # ['get/v1/monitor', 'post/v1/monitor']

    if mypermission in all_permission:
        return True
    else:
        return False

def user_auth():
    print("user auth....")
    token = request.headers.get("token")
    if token:
        s = TJS(current_app.config["SECRET_KEY"])
        try:
            data = s.loads(token)
        except BadSignature:
            print("xxxxxxxxxxxx")
            raise TokenFailException
            # raise  RuntimeError("签名错误")
        except SignatureExpired:
            raise RuntimeError("token过期")
        return data
    else:
        raise RuntimeError("没有拿到token")

"""
api授权 -- 签名认证
1、服务端向客户端提供授权的appid和secretkey，以及加密算法
2、客户端拿到appid和secretkey，按照服务端规定的算法进行hash加密，得到签名
3、客户端将签名发送给服务端，服务端验证
"""

def create_token(uid):
    #第一个参数传递内部私钥,测试环境写死
    #第二个参数是有效期
    s = TJS(current_app.config["SECRET_KEY"], expires_in=current_app.config["EXPIRES_IN"])
    #s = TJS("123456", expires_in=10)
    token = s.dumps({"uid": uid}).decode("ascii")
    return token

# Json Web Token(JWT)   进行web token auth认证信息传递的规范

